package com.atguigu.tingshu.listener;

import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.search.service.SearchService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class SearchMqListener {

    @Autowired
    SearchService searchService;
    @Autowired
    RedisTemplate redisTemplate;

    @RabbitListener(
           bindings = @QueueBinding(
                   value = @Queue(value = RabbitConstant.ALBUM_UPPER_QUEUE),
                   exchange = @Exchange(value = RabbitConstant.ALBUM_EXCHANGE , type = ExchangeTypes.TOPIC),
                   key = {RabbitConstant.ALBUM_UPPER_RK}
           )
    )
    public void albumUpper(Channel channel , Message message,  Long albumId) throws IOException {
        try {
            //幂等性： albumId
            // redis+token
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(RedisConstant.ALBUM_INFO_PREFIX + albumId
                    , 1, 10, TimeUnit.MINUTES);// 返回true表示第一次消费，返回false表示已经消费过了
            if(!flag){
                return;
            }
            searchService.upperAlbum(albumId);// 业务代码
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);// 确认消费成功
            log.info("专辑上架成功，专辑id:{}" , albumId);
        } catch (Exception e) {
            if(message.getMessageProperties().isRedelivered()){
                log.error("专辑上架异常，专辑id:{}" , albumId);
                //丢弃消息
                channel.basicReject( message.getMessageProperties().getDeliveryTag(),false);
                throw new GuiguException(ResultCodeEnum.DATA_ERROR);
            }else{
                //第一次消费异常时需要重试，可以删除redis幂等性token
                redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX + albumId);
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,true);
            }
        }
    }


    //专辑下架
    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(value = RabbitConstant.ALBUM_DOWN_QUEUE),
                    exchange = @Exchange(value = RabbitConstant.ALBUM_EXCHANGE , type = ExchangeTypes.TOPIC),
                    key = {RabbitConstant.ALBUM_DOWN_RK}
            )
    )
    public void albumDown(Channel channel , Message message,  Long albumId) throws IOException {
        try {
            searchService.deleteAlbumInfoIndex(albumId);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            log.info("专辑下架成功，专辑id:{}" , albumId);
        } catch (Exception e) {
            if(message.getMessageProperties().isRedelivered()){
                log.error("专辑下架异常，专辑id:{}" , albumId);
                //丢弃消息
                channel.basicReject( message.getMessageProperties().getDeliveryTag(),false);
                throw new GuiguException(ResultCodeEnum.DATA_ERROR);
            }else{
                //第一次消费异常时需要重试，可以删除redis幂等性token
                redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX + albumId);
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,true);
            }
        }
    }
}
